include "num.pyx"

cdef u8 log2(u64 v):
    cdef u64 i, flag=1
    for i in range(1,64):
        if flag<v:
            flag <<= 1
        else:
            return i
    return 64
#---------------------------------------next arrayset-------------------------------------------------------------------
cdef u64 next_u16_arrayset(void* arrayset, u64 count, u64* iptr):
    cdef u64 i=iptr[0]
    cdef u16* arr=<u16*>arrayset
    if i< count:
        return arr[i]
    else:
        raise RuntimeError("Index out of range")
    
cdef u64 next_u32_arrayset(void* arrayset, u64 count, u64* iptr):
    cdef u64 i=iptr[0]
    cdef u32* arr=<u32*>arrayset
    if i< count:
        return arr[i]
    else:
        raise RuntimeError("Index out of range")
    
cdef u64 next_u64_arrayset(void* arrayset, u64 count, u64* iptr):
    cdef u64 i=iptr[0]
    cdef u64* arr=<u64*>arrayset
    if i< count:
        return arr[i]
    else:
        raise RuntimeError("Index out of range")

cdef u64 next_u24_arrayset(void* arrayset, u64 count, u64* iptr):
    cdef u16* lows=<u16*>arrayset,
    cdef u8 *highs=<u8*>(lows+count)
    cdef u64 i=iptr[0], highv = highs[i]
    if i< count:
        return lows[i] + highv<<16
    else:
        raise RuntimeError("Index out of range")
    
cdef u64 next_u40_arrayset(void* arrayset, u64 count, u64* iptr):
    cdef u32* lows=<u32*>arrayset,
    cdef u8 *highs=<u8*>(lows+count)
    cdef u64 i=iptr[0], highv = highs[i]
    if i< count:
        return lows[i] + highv<<32
    else:
        raise RuntimeError("Index out of range")
    
cdef u64 next_u48_arrayset(void* arrayset, u64 count, u64* iptr):
    cdef u32* lows=<u32*>arrayset,
    cdef u16 *highs=<u16*>(lows+count)
    cdef u64 i=iptr[0], highv = highs[i]
    if i< count:
        return lows[i] + highv<<32
    else:
        raise RuntimeError("Index out of range")
    
#---------------------------------------next hashset-------------------------------------------------------------------
cdef u64 next_u16_hashset(void* hashset, u64 count, u64* iptr):
    cdef u64 i = iptr[0]
    cdef u16* arr=<u16*>hashset
    cdef u8* deleted = <u8*>(arr+count)
    while(i<count):
        if arr[i]==0 or bitset8_get(deleted, i):
            i+=1
        else:
            iptr[0]=i
            return arr[i]
    raise RuntimeError("Index out of range")

cdef u64 next_u32_hashset(void* hashset, u64 count, u64* iptr):
    cdef u64 i = iptr[0]
    cdef u32 * arr = <u32 *> hashset
    cdef u8 * deleted = <u8*> (arr + count)
    while (i < count):
        if arr[i] == 0 or bitset8_get(deleted, i):
            i += 1
        else:
            iptr[0] = i
            return arr[i]
    raise RuntimeError("Index out of range")

cdef u64 next_u64_hashset(void* hashset, u64 count, u64* iptr):
    cdef u64 i = iptr[0]
    cdef u64 * arr = <u64 *> hashset
    cdef u8 * deleted = <u8*> (arr + count)
    while (i < count):
        if arr[i] == 0 or bitset8_get(deleted, i):
            i += 1
        else:
            iptr[0] = i
            return arr[i]
    raise RuntimeError("Index out of range")

cdef u64 next_u24_hashset(void* low, u64 count, u64* iptr):
    cdef u16* lows = <u16*>low
    cdef u8* highs=<u8*>(lows+count)
    cdef u8* deleted = <u8*>(highs+count)
    cdef u64 i = iptr[0], highv=highs[i]
    while (i<count):
        if lows[i] == 0 and highv==0:
            i += 1
            highv = highs[i]
        else:
            iptr[0] = i
            return lows[i]+(highv<<16)
    raise RuntimeError("Index out of range")

cdef u64 next_u40_hashset(void* low, u64 count, u64* iptr):
    cdef u32* lows = <u32*>low
    cdef u8* highs=<u8*>(lows+count)
    cdef u8* deleted = <u8*>(highs+count)
    cdef u64 i = iptr[0], highv=highs[i]
    while (i<count):
        if lows[i] == 0 and highv==0:
            i += 1
            highv = highs[i]
        else:
            iptr[0] = i
            return lows[i]+(highv<<16)
    raise RuntimeError("Index out of range")

cdef u64 next_u48_hashset(void* low, u64 count, u64* iptr):
    cdef u32* lows = <u32*>low
    cdef u16* highs=<u16*>(lows+count)
    cdef u8* deleted = <u8*>(highs+count)
    cdef u64 i = iptr[0], highv=highs[i]
    while (i<count):
        if lows[i] == 0 and highv==0:
            i += 1
            highv = highs[i]
        else:
            iptr[0] = i
            return lows[i]+(highv<<16)
    raise RuntimeError("Index out of range")



#------------------------------------------------bisect -----------------------------------------------------------------------
cdef u64 bisect_u16(void* data, u64 val, uint count, uint* eq):
    cdef u16* arr=<u16*>data
    cdef u64 low=0, high=count, mi
    while(low<high):
        mi = (low+high)>>1
        if arr[mi]<val:
            low = mi + 1
        elif arr[mi]>val:
            high = mi
        else:
            eq[0]=1
            return mi
    eq[0]=0
    return low

cdef u64 bisect_u32(void* data, u64 val, uint count, uint* eq):
    cdef u32* arr=<u32*>data
    cdef u64 low=0, high=count, mi
    while(low<high):
        mi = (low+high)>>1
        if arr[mi]<val:
            low = mi + 1
        elif arr[mi]>val:
            high = mi
        else:
            eq[0]=1
            return mi
    eq[0]=0
    return low

cdef u64 bisect_u64(void* data, u64 val, uint count, uint* eq):
    cdef u64* arr=<u64*>data
    cdef u64 low=0, high=count, mi
    while(low<high):
        mi = (low+high)>>1
        if arr[mi]<val:
            low = mi + 1
        elif arr[mi]>val:
            high = mi
        else:
            eq[0]=1
            return mi
    eq[0]=0
    return low

cdef u64 bisect_u24(void* data, u64 val, uint count, uint* eq):
    cdef u16* lows = <u16*>data
    cdef u8* highs = <u8*>(lows+count)
    cdef u64 low=0, high=count, mi, mid, highv
    while(low<high):
        mi = (low+high)>>1
        highv = highs[mi]
        mid = (highv<<16) + lows[mi]
        if mid<val:
            low = mi + 1
        elif mid>val:
            high = mi
        else:
            eq[0]=1
            return mi
    eq[0]=0
    return low

cdef u64 bisect_u40(void* data, u64 val, uint count, uint* eq):
    cdef u32* lows = <u32*>data
    cdef u8* highs = <u8*>(lows+count)
    cdef u64 low=0, high=count, mi, mid, highv
    while(low<high):
        mi = (low+high)>>1
        highv = highs[mi]
        mid = (highv<<32) + lows[mi]
        if mid<val:
            low = mi + 1
        elif mid>val:
            high = mi
        else:
            eq[0]=1
            return mi
    eq[0]=0
    return low

cdef u64 bisect_u48(void* data, u64 val, uint count, uint* eq):
    cdef u32* lows = <u32*>data
    cdef u16* highs = <u16*>(lows+count)
    cdef u64 low=0, high=count, mi, mid, highv
    while(low<high):
        mi = (low+high)>>1
        highv = highs[mi]
        mid = (highv<<32) + lows[mi]
        if mid<val:
            low = mi + 1
        elif mid>val:
            high = mi
        else:
            eq[0]=1
            return mi
    eq[0]=0
    return low
#------------------------------------------------bisect in--------------------------------------------------------------
cdef u64 bisect_u16_in(void* data, u64 val, uint count):
    cdef uint eq
    cdef u64 i=bisect_u16(data, val, count, &eq)
    return i if eq else UINT64_MAX

cdef u64 bisect_u32_in(void* data, u64 val, uint count):
    cdef uint eq
    cdef u64 i=bisect_u32(data, val, count, &eq)
    return i if eq else UINT64_MAX

cdef u64 bisect_u64_in(void* data, u64 val, uint count):
    cdef uint eq
    cdef u64 i=bisect_u64(data, val, count, &eq)
    return i if eq else UINT64_MAX

cdef u64 bisect_u24_in(void* data, u64 val, uint count):
    cdef uint eq
    cdef u64 i=bisect_u24(data, val, count, &eq)
    return i if eq else UINT64_MAX

cdef u64 bisect_u40_in(void* data, u64 val, uint count):
    cdef uint eq
    cdef u64 i=bisect_u40(data, val, count, &eq)
    return i if eq else UINT64_MAX

cdef u64 bisect_u48_in(void* data, u64 val, uint count):
    cdef uint eq
    cdef u64 i=bisect_u48(data, val, count, &eq)
    return i if eq else UINT64_MAX


#-----------------------------------------------bisect insert-----------------------------------------------------------

cdef u64 bisect_insert_u16(void* data, u64 val, u64 count, void* cur):
    cdef u16* arr=<u16*>data
    cdef uint eq, i=bisect_u16(arr, val, count, &eq)
    if eq:
        return UINT64_MAX
    else:
        memmove(arr+i+1, arr+i, (count-i)*sizeof(u16))
        arr[i]=val
        (<u8 *> cur)[0] += 1
        return i
    
cdef u64 bisect_insert_u32(void* data, u64 val, u64 count, void* cur):
    cdef u32* arr=<u32*>data
    cdef uint eq, i=bisect_u32(arr, val, count, &eq)
    if eq:
        return UINT64_MAX
    else:
        memmove(arr+i+1, arr+i, (count-i)*sizeof(u32))
        arr[i]=val
        (<u8 *> cur)[0] += 1
        return i
    
cdef u64 bisect_insert_u64(void* data, u64 val, u64 count, void* cur):
    cdef u64* arr=<u64*>data
    cdef uint eq, i=bisect_u64(arr, val, count, &eq)
    if eq:
        return UINT64_MAX
    else:
        memmove(arr+i+1, arr+i, (count-i)*sizeof(u64))
        arr[i]=val
        (<u8 *> cur)[0] += 1
        return i

cdef u64 bisect_insert_u24(void* data, u64 val, u64 count, void* cur):
    cdef u16* low=<u16*>data
    cdef u8* high = < u8*>(low+count)
    cdef uint eq, i=bisect_u24(data, val, count, &eq)
    if eq:
        return UINT64_MAX
    else:
        memmove(low + i + 1, low + i, (count - i) * sizeof(u16))
        memmove(high+i+1, high+i, (count-i)*sizeof(u8))
        low[i]=val&UINT16_MAX
        high[i]=(val>>16)
        (<u8 *> cur)[0] += 1
        return i

cdef u64 bisect_insert_u40(void* data, u64 val, u64 count, void* cur):
    cdef u32* low=<u32*>data
    cdef u8* high = < u8*>(low+count)
    cdef uint eq, i=bisect_u24(data, val, count, &eq)
    if eq:
        return UINT64_MAX
    else:
        memmove(low + i + 1, low + i, (count - i) * sizeof(u32))
        memmove(high+i+1, high+i, (count-i)*sizeof(u8))
        low[i]=val&UINT32_MAX
        high[i]=(val>>32)
        (<u8 *> cur)[0] += 1
        return i
    

cdef u64 bisect_insert_u48(void* data, u64 val, u64 count, void* cur):
    cdef u32* low=<u32*>data
    cdef u16* high = < u16*>(low+count)
    cdef uint eq, i=bisect_u48(data, val, count, &eq)
    if eq:
        return UINT64_MAX
    else:
        memmove(low + i + 1, low + i, (count - i) * sizeof(u32))
        memmove(high+i+1, high+i, (count-i)*sizeof(u8))
        low[i]=val&UINT32_MAX
        high[i]=(val>>32)
        (<u8 *> cur)[0] += 1
        return i

#--------------------------------------------------bisect remove--------------------------------------------------------

cdef u64 bisect_remove_u16(void* data, u64 val, u64 count, void* cur):
    cdef u16* arr=<u16*>data
    cdef uint eq, i=bisect_u16(arr, val, count, &eq), ii, j
    cdef uInt temp0, temp1
    if eq:
        for ii in range(i,count-1):
            arr[ii]=arr[ii+1]
        (<u8 *> cur)[0] -= 1
        return i
    else:
        return UINT64_MAX

cdef u64 bisect_remove_u32(void* data, u64 val, u64 count, void* cur):
    cdef u32* arr=<u32*>data
    cdef uint eq, i=bisect_u32(arr, val, count, &eq), ii, j
    cdef uInt temp0, temp1
    if eq:
        for ii in range(i,count-1):
            arr[ii]=arr[ii+1]
        (<u8 *> cur)[0] -= 1
        return i
    else:
        return UINT64_MAX

cdef u64 bisect_remove_u64(void* data, u64 val, u64 count, void* cur):
    cdef u64* arr=<u64*>data
    cdef uint eq, i=bisect_u64(arr, val, count, &eq), ii, j
    cdef uInt temp0, temp1
    if eq:
        for ii in range(i,count-1):
            arr[ii]=arr[ii+1]
        (<u8 *> cur)[0] -= 1
        return i
    else:
        return UINT64_MAX

cdef u64 bisect_insert_u24(void* data, u64 val, u64 count, void* cur):
    cdef u16* low=<u16*>data
    cdef u8* high = < u8*>(low+count)
    cdef uint eq, i=bisect_u24(data, val, count, &eq)
    if eq:
        return UINT64_MAX
    else:
        memmove(low + i + 1, low + i, (count - i) * sizeof(u16))
        memmove(high+i+1, high+i, (count-i)*sizeof(u8))
        low[i]=val&UINT16_MAX
        high[i]=(val>>16)
        (<u8 *> cur)[0] += 1
        return i
    
cdef u64 bisect_remove_u24(void* data, u64 val, u64 count, void* cur):
    cdef u16 * low = <u16 *> data
    cdef u8 * high = <u8 *> (low + count)
    cdef uint eq, i=bisect_u24(data, val, count, &eq), ii, j
    if eq:
        for ii in range(i,count-1):
            low[ii]=low[ii+1]
            high[ii]=high[ii+1]
        (<u8 *> cur)[0] -= 1
        return i
    else:
        return UINT64_MAX
cdef u64 bisect_remove_u40(void* data, u64 val, u64 count, void* cur):
    cdef u32 * low = <u32 *> data
    cdef u8 * high = <u8 *> (low + count)
    cdef uint eq, i=bisect_u40(data, val, count, &eq), ii, j
    if eq:
        for ii in range(i,count-1):
            low[ii]=low[ii+1]
            high[ii]=high[ii+1]
        (<u8 *> cur)[0] -= 1
        return i
    else:
        return UINT64_MAX
cdef u64 bisect_remove_u48(void* data, u64 val, u64 count, void* cur):
    cdef u32 * low = <u32 *> data
    cdef u8 * high = <u8 *> (low + count)
    cdef uint eq, i=bisect_u48(data, val, count, &eq), ii, j
    if eq:
        for ii in range(i,count-1):
            low[ii]=low[ii+1]
            high[ii]=high[ii+1]
        (<u8 *> cur)[0] -= 1
        return i
    else:
        return UINT64_MAX
    
    
    
#---------------------------------------------------bitset in-----------------------------------------------------------
cdef u64 ONE=1

cdef u64 next_bitset_1(u64 v, u64 i, u64 start_bit, u64* iptr):
    cdef u64 ibit, flag=ONE<<start_bit,vv
    for ibit in range(start_bit,64):
        ##print(f'flag={flag}, v={str_bitstring(v)}, ibit={ibit}, i={i}, debug next bitset_1')
        if v&flag:
            vv=(i<<6) + ibit
            iptr[0] = vv
            return vv
        else:
            flag<<=1
    return 0

cdef u64 bitset64_next(void* _data, u64 count, u64 * i):
    cdef u64* data=<u64*>_data
    cdef u64 ii = i[0], iii = ii >> 6, jj = ii & 63, flag = ONE << jj, v, jjj, j
    if ii<count:
        v=data[iii]
    else:
        raise RuntimeError('Index out of range')
    j=next_bitset_1(v, iii, jj, i)
    if j!=0:
        return j
    while(1):
        iii+=1
        v=data[iii]
        ##print(f'iii={iii}, v={str_bitstring(v)}, j={j}, debug next bitset')
        if v==0:continue
        else:
            j=next_bitset_1(v, iii, 0, i)
            ##print(f'j={j}, iii={iii}, v={str_bitstring(v)}, debug next bitset')
            assert j!=0
            return j

cdef inline u64 bitset8_get(void* data, u64 index):
    cdef u8* arr = <u8*>data
    return (arr[index>>3]>>(index&7))&ONE

cdef inline u64 bitset8_set1(void* data, u64 index):
    cdef u8* arr = <u8*>data
    cdef u64 i=index>>3, j=index&7, v=arr[i], flag=ONE<<j, vv=v|flag
    arr[i]=vv
    return vv-v

cdef inline u64 bitset8_set0(void* data, u64 index):
    cdef u8* arr = <u8*>data
    cdef u64 i=index>>3, j=index&7, v=arr[i], flag=~(ONE<<j), vv=v&flag
    arr[i]=vv
    return vv-v

cdef u64 bitset64_in(void* data, u64 _, u64 val):
    cdef u64 eq=bitset8_get(data, val)
    return eq
cdef u64 bitset64_insert(void* data, u64 _, u64 val):
    return bitset8_set1(data, val)!=0

cdef u64 bitset64_remove(void* data, u64 _, u64 val):
    return bitset8_set0(data, val)

#---------------------------------------hash in-------------------------------------------------------------------------
cdef uint PERTURB_SHIFT=5
cdef u64 u16_hash_search_in(void* data, u64 mask, u64 val):
    cdef u64 perturb = val, i=val&mask, j, count=mask+1
    cdef u8 stat
    cdef u16 *hashset=<u16*>data, *deleted=hashset+count
    while(1):
        if hashset[i]==0:
            return UINT64_MAX
        elif hashset[i]!=val:
            perturb >>= PERTURB_SHIFT
            i = mask & (i * 5 + perturb + 1)
        elif bitset8_get(deleted, i)==0:
            return i
        else:
            return UINT64_MAX
    raise AssertionError('Unreachable')

cdef u64 u32_hash_search_in(void* data, u64 mask, u64 val):
    cdef u64 perturb = val, i=val&mask, j, count=mask+1
    cdef u8 stat
    cdef u32 *hashset=<u32*>data, *deleted=hashset+count
    while(1):
        if hashset[i]==0:
            return UINT64_MAX
        elif hashset[i]!=val:
            perturb >>= PERTURB_SHIFT
            i = mask & (i * 5 + perturb + 1)
        elif bitset8_get(deleted, i)==0:
            return i
        else:
            return UINT64_MAX
    raise AssertionError('Unreachable')

cdef u64 u64_hash_search_in(void* data, u64 mask, u64 val):
    cdef u64 perturb = val, i=val&mask, j, count=mask+1
    cdef u8 stat
    cdef u64 *hashset=<u64*>data, *deleted=hashset+count
    while(1):
        if hashset[i]==0:
            return UINT64_MAX
        elif hashset[i]!=val:
            perturb >>= PERTURB_SHIFT
            i = mask & (i * 5 + perturb + 1)
        elif bitset8_get(deleted, i)==0:
            return i
        else:
            return UINT64_MAX
    raise AssertionError('Unreachable')

cdef u64 u24_hash_search_in(void* data, u64 mask, u64 val):
    cdef u64 perturb = val, v, i=val&mask, j, count=mask+1
    cdef u16 * low = <u16 *> data
    cdef u8 *high = <u8 *> (low + count), *deleted=high+count
    while(1):
        v = ((<u64>high[i])<<16) + low[i]
        if v==0: #遇到一个从未使用过的槽，探测链结束
            return UINT64_MAX
        elif v!=val: # 值不相等，探测链继续
            perturb >>= PERTURB_SHIFT
            i = mask & (i * 5 + perturb + 1)
        elif bitset8_get(deleted, i) == 0: # 值相等，但是这个值已被删除
            perturb >>= PERTURB_SHIFT
            i = mask & (i * 5 + perturb + 1)
        else:
            return UINT64_MAX
    raise AssertionError('Unreachable')

cdef u64 u40_hash_search_in(void* data, u64 mask, u64 val):
    cdef u64 perturb = val, v, i=val&mask, j, count=mask+1
    cdef u32 * low = <u32 *> data
    cdef u8 *high = <u8 *> (low + count), *deleted=high+count
    while(1):
        v = ((<u64>high[i])<<32) + low[i]
        if v==0: #遇到一个从未使用过的槽，探测链结束
            return UINT64_MAX
        elif v!=val: # 值不相等，探测链继续
            perturb >>= PERTURB_SHIFT
            i = mask & (i * 5 + perturb + 1)
        elif bitset8_get(deleted, i) == 0: # 值相等，但是这个值已被删除
            perturb >>= PERTURB_SHIFT
            i = mask & (i * 5 + perturb + 1)
        else:
            return UINT64_MAX
    raise AssertionError('Unreachable')

cdef u64 u48_hash_search_in(void* data, u64 mask, u64 val):
    cdef u64 perturb = val, v, i=val&mask, j, count=mask+1
    cdef u32 * low = <u32 *> data
    cdef u16 *high = <u16 *> (low + count)
    cdef u8* deleted=<u8 *> (high+ count)
    while(1):
        v = ((<u64>high[i])<<16) + low[i]
        if v==0: #遇到一个从未使用过的槽，探测链结束
            return UINT64_MAX
        elif v!=val: # 值不相等，探测链继续
            perturb >>= PERTURB_SHIFT
            i = mask & (i * 5 + perturb + 1)
        elif bitset8_get(deleted, i) == 0: # 值相等，但是这个值已被删除
            perturb >>= PERTURB_SHIFT
            i = mask & (i * 5 + perturb + 1)
        else:
            return UINT64_MAX
    raise AssertionError('Unreachable')
#---------------------------------------hash insert------------------------------------------------------------------
cdef u64 u16_hash_insert(void* data, u64 mask, u64 val):
    cdef u64 perturb = val, i=val&mask, j, count=mask+1
    cdef u8 stat
    cdef u16 *hashset=<u16*>data, *deleted=hashset+count
    while(1):
        if hashset[i]==0:
            hashset[i]=val
            return i
        elif bitset8_get(deleted, i):  # 找到一个被删除的槽
            hashset[i] = val
            return i
        elif hashset[i]!=val:
            perturb >>= PERTURB_SHIFT
            i = mask & (i * 5 + perturb + 1)
            #print(f'hashset[{i}]={hashset[i]}, pertub={perturb}, mask={mask}, val={val},debug u16 hash insert')
        else:
            return UINT64_MAX
    raise AssertionError('Unreachable')
cdef u64 u32_hash_insert(void* data, u64 mask, u64 val):
    cdef u64 perturb = val, i=val&mask, j, count=mask+1
    cdef u8 stat
    cdef u32 *hashset=<u32*>data, *deleted=hashset+count
    while(1):
        if hashset[i]==0:
            hashset[i]=val
            return i
        elif bitset8_get(deleted, i):  # 找到一个被删除的槽
            hashset[i] = val
            return i
        elif hashset[i]!=val:
            perturb >>= PERTURB_SHIFT
            i = mask & (i * 5 + perturb + 1)
            #print(f'hashset[{i}]={hashset[i]}, pertub={perturb}, mask={mask}, val={val},debug u32 hash insert')
        else:
            return UINT64_MAX
    raise AssertionError('Unreachable')
cdef u64 u64_hash_insert(void* data, u64 mask, u64 val):
    cdef u64 perturb = val, i=val&mask, j, count=mask+1
    cdef u8 stat
    cdef u64 *hashset=<u64*>data, *deleted=hashset+count
    while(1):
        if hashset[i]==0:
            hashset[i]=val
            return i
        elif bitset8_get(deleted, i):  # 找到一个被删除的槽
            hashset[i] = val
            return i
        elif hashset[i]!=val:
            perturb >>= PERTURB_SHIFT
            i = mask & (i * 5 + perturb + 1)
            #print(f'hashset[{i}]={hashset[i]}, pertub={perturb}, mask={mask}, val={val},debug u64 hash insert')
        else:
            return UINT64_MAX
    raise AssertionError('Unreachable')

cdef u64 u24_hash_insert(void* data, u64 mask, u64 val):
    cdef u64 perturb = val, v, i=val&mask, j, count=mask+1
    cdef u16 * low = <u16 *> data
    cdef u8 *high = <u8 *> (low + count), *deleted=high+count
    while(1):
        v = ((<u64>high[i])<<16) + low[i]
        if v==0: #找到一个从未使用过的槽
            low[i]=val&UINT16_MAX
            high[i]=val>>16
            return i
        elif bitset8_get(deleted, i): # 找到一个被删除的槽
            low[i] = val & UINT16_MAX
            high[i] = val >> 16
            return i
        elif v!=val: # 一个正在被其他值占用的槽
            perturb >>= PERTURB_SHIFT
            i = mask & (i * 5 + perturb + 1)
        else:
            return UINT64_MAX
    raise AssertionError('Unreachable')

cdef u64 u40_hash_insert(void* data, u64 mask, u64 val):
    cdef u64 perturb = val, v, i=val&mask, j, count=mask+1
    cdef u32 * low = <u32 *> data
    cdef u8 *high = <u8 *> (low + count), *deleted=high+count
    while(1):
        v = ((<u64>high[i])<<32) + low[i]
        if v==0: #找到一个从未使用过的槽
            low[i]=val&UINT32_MAX
            high[i]=val>>32
            return i
        elif bitset8_get(deleted, i): # 找到一个被删除的槽
            low[i] = val & UINT32_MAX
            high[i] = val >> 32
            return i
        elif v!=val: # 一个正在被其他值占用的槽
            perturb >>= PERTURB_SHIFT
            i = mask & (i * 5 + perturb + 1)
        else:
            return UINT64_MAX
    raise AssertionError('Unreachable')

cdef u64 u48_hash_insert(void* data, u64 mask, u64 val):
    cdef u64 perturb = val, v, i=val&mask, j, count=mask+1
    cdef u32 * low = <u32 *> data
    cdef u16 *high = <u16 *> (low + count)
    cdef u8* deleted=<u8 *>(high+count)
    while(1):
        v = ((<u64>high[i])<<32) + low[i]
        if v==0: #找到一个从未使用过的槽
            low[i]=val&UINT32_MAX
            high[i]=val>>32
            return i
        elif bitset8_get(deleted, i): # 找到一个被删除的槽
            low[i] = val & UINT32_MAX
            high[i] = val >> 32
            return i
        elif v!=val: # 一个正在被其他值占用的槽
            perturb >>= PERTURB_SHIFT
            i = mask & (i * 5 + perturb + 1)
        else:
            return UINT64_MAX
    raise AssertionError('Unreachable')

#---------------------------------------hash remove------------------------------------------------------------------
cdef u64 u16_hash_remove(void* data, u64 mask, u64 val):
    cdef u64 perturb = val, i=u16_hash_search_in(data, mask, val), j, count=mask+1
    cdef u8 stat
    cdef u16 *hashset=<u16*>data, *deleted=hashset+count
    if i!=UINT64_MAX:
        bitset8_set1(deleted, i)
    return i

cdef u64 u32_hash_remove(void* data, u64 mask, u64 val):
    cdef u64 perturb = val, i=u32_hash_search_in(data, mask, val), j, count=mask+1
    cdef u8 stat
    cdef u32 *hashset=<u32*>data, *deleted=hashset+count
    if i!=UINT64_MAX:
        bitset8_set1(deleted, i)
    return i

cdef u64 u64_hash_remove(void* data, u64 mask, u64 val):
    cdef u64 perturb = val, i=u64_hash_search_in(data, mask, val), j, count=mask+1
    cdef u8 stat
    cdef u64 *hashset=<u64*>data, *deleted=hashset+count
    if i!=UINT64_MAX:
        bitset8_set1(deleted, i)
    return i

cdef u64 u24_hash_remove(void* data, u64 mask, u64 val):
    cdef u64 perturb = val, i=u24_hash_search_in(data, mask, val), j, count=mask+1
    cdef u8 stat
    cdef u16 *lows=<u16*>data
    cdef u8* highs=<u8*>(lows+count)
    cdef u8* deleted=highs+count
    if i!=UINT64_MAX:
        bitset8_set1(deleted, i)
    return i


cdef u64 u40_hash_remove(void* data, u64 mask, u64 val):
    cdef u64 perturb = val, i = u40_hash_search_in(data, mask, val), j, count = mask + 1
    cdef u8 stat
    cdef u32 *lows = <u32 *> data
    cdef u8 * highs = <u8 *> (lows + count)
    cdef u8 * deleted = highs + count
    if i != UINT64_MAX:
        bitset8_set1(deleted, i)
    return i

cdef u64 u48_hash_remove(void* data, u64 mask, u64 val):
    cdef u64 perturb = val, i = u48_hash_search_in(data, mask, val), j, count = mask + 1
    cdef u8 stat
    cdef u32 *lows = <u32 *> data
    cdef u16 * highs = <u16 *> (lows + count)
    cdef u8 * deleted = <u8 *> (highs + count)
    if i != UINT64_MAX:
        bitset8_set1(deleted, i)
    return i

#-----------------------------------------------------------------------------------------------------------------------

cdef UintSet _copy_to_new_set(UintSet set0, UintSet set1, void* data0, void* data1, uintSetArgs* arg0, uintSetArgs* arg1, uintSetFuncs* func0, uintSetFuncs* func1, u64 cur):
    cdef u64 v, i=0, count
    for count in range(cur):
        v = func0.next_func(data0, arg0.mask_or_capacity, &count)
        uint_set_insert_val(set1, val, arg1, func1, cur, data1)
        i+=1
    return set1

cdef inline UintSet _copy_to_new_set_insert(UintSet set0, UintSet set1, uintSetArgs* arg0, uintSetArgs* arg1, uintSetFuncs* func0, uintSetFuncs* func1, u64 cur, u64 val):
    cdef u64 v, i = 0, count
    cdef void* data0=set0._data(), *data1=set1._data()
    _copy_to_new_set(set0, set1, data0, data1, arg0, arg1, func0, func1, cur)
    uint_set_insert_val(set1, val, arg1, func1, cur, data1)
    return set1

cdef inline UintSet _copy_to_new_set_remove(UintSet set0, UintSet set1, uintSetArgs* arg0, uintSetArgs* arg1, uintSetFuncs* func0, uintSetFuncs* func1, u64 cur, u64 val):
    cdef u64 v, i = 0, count
    cdef void* data0=set0._data(), *data1=set1._data()
    _copy_to_new_set(set0, set1, data0, data1, arg0, arg1, func0, func1, cur)
    uint_set_remove_val(set1, val, arg1, func1, cur, data1)
    return set1

cpdef UintSet size_choose_uint_set(u8 itemsize, u64 cur, u8 cur_level):
    cdef uintSetArgs * args = UINT_SET_SET_ARGS[itemsize], *arg=args+cur_level
    cdef u8 i
    cdef tuple classes
    if cur_level <HASH_LEVEL_MAXS[itemsize]:
        if cur_level < 4:
            classes = UINT_ARRAY_CLASSES[itemsize]
            t = UINT_ARRAY_CLASSES[cur_level]
            return t()
        else:
            t = UINT_HASH_SETS[itemsize]
            return t()
    else:
        return UintBitSet().set_itemsize(itemsize).init(cur) if itemsize!=1 else U8BitSet().set_itemsize(itemsize).init(cur)
    
cdef inline uint_set_insert_val(UintSet self, u64 val, uintSetArgs* arg, uintSetFuncs* func, u64 cur, void* data ):
    if func.insert_func(data, arg.mask_or_capacity, val) != UINT64_MAX:
        self.set_cur(cur + 1)
        
cdef inline uint_set_remove_val(UintSet self, u64 val, uintSetArgs* arg, uintSetFuncs* func, u64 cur, void* data ):
    if func.remove_func(data, arg.mask_or_capacity, val) != UINT64_MAX:
        self.set_cur(cur + 1)

cdef u64 uint_set_contains(void* data, u8 itemsize, u8 cur_level, u64 val, u64 cur, UintSet self,uintSetFuncs* func, uintSetArgs* arg):
    if val<UINT_MAXS[itemsize]:
        return func.search_func(data, arg.mask_or_capacity, val)
    else:
        return 0

cdef UintSet uint_set_add(void* data, u8 itemsize, u8 cur_level, u64 val, u64 cur, UintSet self):
    cdef u8 val_itemsize, val_level, level_s
    cdef uintSetArgs *arg0, *arg1
    cdef uintSetFuncs *func0, *func1
    cdef UintSet s
    self._get_arg_funcs(&arg0, &func0)
    if val<UINT_MAXS[itemsize]:
        if cur<arg0.maxsize:
            uint_set_insert_val(self, val, arg0,  cur, data)
            return self
        else:
            s = size_choose_uint_set(itemsize, cur, cur_level+1)
            s._get_arg_funcs(&arg1, &func1)
            _copy_to_new_set_insert(self, s, arg0, arg1, func0, func1, cur, val )
            return s
    else:
        val_itemsize = value_get_itemsize(val, itemsize)
        s = size_choose_uint_set(val_itemsize, cur, cur_level+1)
        s._get_arg_funcs(&arg1, &func1)
        _copy_to_new_set_insert(self, s, arg0, arg1, func0, func1, cur, val)
        return s

cdef UintSet uint_set_remove(void * data, u8 itemsize, u8 cur_level, u64 val, u64 cur, UintSet self):
    cdef u8 val_itemsize, val_level, level_s
    cdef uintSetArgs *arg0, *arg1
    cdef uintSetFuncs *func0, *func1
    cdef UintSet s
    self._get_arg_funcs(&arg0, &func0)
    if val < UINT_MAXS[itemsize]:
        if cur < arg0.maxsize:
            uint_set_remove_val(self, val, arg0, cur, data)
            return self
        else:
            s = size_choose_uint_set(itemsize, cur, cur_level+1)
            s._get_arg_funcs(&arg1, &func1)
            _copy_to_new_set_remove(self, s, arg0, arg1, func0, func1, cur, val)
            return s
    else:
        return self

#-----------------------------------------------------------------------------------------------------------------------
ctypedef u64 next_u64_func(void * data, u64 count, u64 * iptr)
ctypedef u64 search_insert_remove_append_func(void * data, u64 mask_or_count, u64 val)

cdef struct uintSetArgs:
    u64 minsize, maxsize, mask_or_capacity

cdef struct uintSetFuncs:
    next_u64_func * next_func
    search_insert_remove_append_func * search_func
    search_insert_remove_append_func * insert_func
    search_insert_remove_append_func * remove_func

cdef uintSetFuncs U16ArraySetFuncs = uintSetFuncs(&next_u16_arrayset, &bisect_u16_in, &bisect_insert_u16, &bisect_remove_u16)
cdef uintSetFuncs U32ArraySetFuncs = uintSetFuncs(&next_u32_arrayset, &bisect_u32_in, &bisect_insert_u32, &bisect_remove_u32)
cdef uintSetFuncs U64ArraySetFuncs = uintSetFuncs(&next_u64_arrayset, &bisect_u64_in, &bisect_insert_u64, &bisect_remove_u64)
cdef uintSetFuncs U24ArraySetFuncs = uintSetFuncs(&next_u24_arrayset, &bisect_u24_in, &bisect_insert_u24, &bisect_remove_u24)
cdef uintSetFuncs U40ArraySetFuncs = uintSetFuncs(&next_u40_arrayset, &bisect_u40_in, &bisect_insert_u40, &bisect_remove_u40)
cdef uintSetFuncs U48ArraySetFuncs = uintSetFuncs(&next_u48_arrayset, &bisect_u48_in, &bisect_insert_u48, &bisect_remove_u48)

cdef uintSetFuncs U16HashSetFuncs = uintSetFuncs(&next_u16_hashset, &u16_hash_search_in, &u16_hash_insert,
                                                 &u16_hash_remove)
cdef uintSetFuncs U32HashSetFuncs = uintSetFuncs(&next_u32_hashset, &u32_hash_search_in, &u32_hash_insert,
                                                 &u32_hash_remove)
cdef uintSetFuncs U64HashSetFuncs = uintSetFuncs(&next_u64_hashset, &u64_hash_search_in, &u64_hash_insert,
                                                 &u64_hash_remove)
cdef uintSetFuncs U24HashSetFuncs = uintSetFuncs(&next_u24_hashset, &u24_hash_search_in, &u24_hash_insert,
                                                 &u24_hash_remove)
cdef uintSetFuncs U40HashSetFuncs = uintSetFuncs(&next_u40_hashset, &u40_hash_search_in, &u40_hash_insert,
                                                 &u40_hash_remove)
cdef uintSetFuncs U48HashSetFuncs = uintSetFuncs(&next_u48_hashset, &u48_hash_search_in, &u48_hash_insert,
                                                 &u48_hash_remove)
cdef uintSetFuncs BitSetFuncs = uintSetFuncs(&bitset64_next, &bitset64_in, &bitset64_insert, &bitset64_remove)

cdef uintSetFuncs* get_funcs(u8 itemsize, u8 level):
    if level<HASH_LEVEL_MAXS[itemsize]:
        if level<5:
            return ARRAY_SET_FUNCS+level
        else:
            return  HASH_LEVEL_MAXS + level
    else:
        return &BitSetFuncs
        
cdef u64[6] UINT_MAXS = [ UINT8_MAX, UINT16_MAX, UINT24_MAX, UINT32_MAX, UINT40_MAX, UINT48_MAX]
cdef u8[6] HASH_LEVEL_MAXS = [1, 11, 20, 27, 35, 43, 0, 58]
cdef uintSetFuncs[6] HASH_SET_FUNCS=[NULL, U16HashSetFuncs, U32HashSetFuncs, U40HashSetFuncs, U48HashSetFuncs, NULL, U64HashSetFuncs]
cdef uintSetFuncs[6] ARRAY_SET_FUNCS=[NULL, U16ArraySetFuncs, U32ArraySetFuncs, U40ArraySetFuncs, U48ArraySetFuncs, NULL, U64ArraySetFuncs]
cdef tuple UINT_HASH_SETS=[None, U16HashSet, U24HashSet, U32HashSet, U40HashSet, U48HashSet, None, U64HashSet]
cdef tuple UINT_BIT_SETS=[U8BitSet, UintBitSet, UintBitSet, UintBitSet, UintBitSet, UintBitSet, None, UintBitSet]

cdef uintSetArgs* UINT_SET_SET_ARGS[8]
cdef uintSetArgs U8SET_ARGS = uintSetArgs(0,23,23)
cdef uintSetArgs[16] U16SET_ARGS
cdef uintSetArgs[24] U24SET_ARGS
cdef uintSetArgs[32] U32SET_ARGS
cdef uintSetArgs[40] U40SET_ARGS
cdef uintSetArgs[48] U48SET_ARGS
cdef uintSetArgs[64] U64SET_ARGS
cdef uintSetArgs[8] UINT_BIT_SET_ARGS
cdef list UINT_ARRAY_CLASSES=[None]*8

init_UINT_SET_SET_ARGS(2, 7)
init_UINT_SET_SET_ARGS(3, 5)
init_UINT_SET_SET_ARGS(4, 5)
init_UINT_SET_SET_ARGS(5, 3)
init_UINT_SET_SET_ARGS(6, 5)
init_UINT_SET_SET_ARGS(8, 4)
cdef init_UINT_SET_SET_ARGS(u8 itemsize, u8 first_itemcount, u64 hash_max_level):
    cdef uintSetArgs* args=UINT_SET_SET_ARGS[itemsize]
    cdef u64 i, pre_minsize=0, pre_maxsize=0, maxsize, minsize
    for i in range(5):
        maxsize = first_itemcount + i<<3
        minsize = (pre_minsize + pre_maxsize)>>1
        args[i] = uintSetArgs(minsize, maxsize, maxsize)
        pre_maxsize = maxsize
        pre_minsize = minsize
    for i in range(5, 1<<itemsize):
        maxsize=3*((ONE<<i)>>2)
        minsize = (pre_minsize + pre_maxsize) >> 1
        mask = (ONE<<i)-1
        args[i] = uintSetArgs(minsize, maxsize, mask)
        pre_maxsize = maxsize
        pre_minsize = minsize
    #
    minsize = (pre_minsize + pre_maxsize) >> 1
    u64n = (ONE << i)>>6
    UINT_BIT_SET_ARGS[itemsize]= uintSetArgs(minsize, UINT64_MAX, u64n)

cdef u8 value_get_itemsize(u64 value, u8 cur_itemsize):
    cdef u8 i
    for i in range(cur_itemsize+1, 6):
        if value<=UINT_MAXS[i]: return i+1
    return 8

cdef get_buffer_array(typecode, u8* data, u64 nbytes):
    cdef array arr = array(typecode)
    resize(arr, <u64>(nbytes/arr.ob_descr.itemsize))
    memcpy(arr.data.as_uchars, data, nbytes)
    return arr

cdef class UintSet:
    cdef u64 _itemsize(self):NotImplemented
    cdef void* _data(self): NotImplemented
    cdef u64 _cur(self): NotImplemented
    cdef set_cur(self, u64 cur): NotImplemented
    cdef u8 _level(self): NotImplemented
    cpdef UintSet init(self, u64 level): NotImplemented
    def __dealloc__(self):
        if self._level()>5:
            PyMem_Free(self._data())
    cpdef get_buffer_array(self):
        if self._itemsize()==2: typecode='H'
        elif self._itemsize()==4: typecode='L'
        elif self._itemsize()==8: typecode='Q'
        else:  typecode='B'
        return get_buffer_array(typecode, <u8*>self._data(), self.nbytes())
    cdef uintSetArgs* _arg(self):
        cdef u8 itemsize = self._itemsize()
        cdef uintSetArgs* args = UINT_SET_SET_ARGS[itemsize]
        return args+self._level()
    cdef inline _get_arg_funcs(self, uintSetArgs** arg, uintSetFuncs** func):
        func[0] = get_funcs(self._itemsize(), self._level())
        arg[0] = self._arg()
    cdef u64 _nbytes(self):
        cdef uintSetArgs * arg = self._arg()
        cdef u64 count = arg.mask_or_capacity if self._level()<6 else arg.mask_or_capacity+1
        return self._itemsize() * count
    cpdef UintSet add(self, u64 val):
        return uint_set_add(self._data(), self._itemsize(), self._level(), self._cur(), val, self)
    cpdef UintSet remove(self, u64 val):
        return uint_set_remove(self._data(), self._itemsize(), self._level(), self._cur(), val, self)
    cpdef u64 contains(self, u64 val):
        return uint_set_contains(self._data(), self._itemsize(), self._level(), self._cur(), val, self)
    @property
    def nbytes(self):
        return self._nbytes()
    @property
    def address(self):
        return <u64>self._data()
    @property
    def level(self):
        return self._level()
    @property
    def itemsize(self):
        return self._itemsize()
    def __len__(self):
        return self._cur()

cdef class UintArraySet(UintSet):
    cdef readonly u8 cur
    cdef inline u64 _cur(self): return self.cur
    cdef inline set_cur(self, u64 cur): self.cur = cur
    cpdef UintSet init(self, u64 level):
        self.cur = 0
        return self

cdef class UintHashSet(UintSet):
    cdef inline void* data
    cdef readonly u64 cur
    cdef readonly u8 level
    cdef uintSetArgs * _arg(self):
        cdef u8 itemsize = self._itemsize()
        cdef uintSetArgs * args = UINT_SET_SET_ARGS[itemsize]
        return args + self._level()
    cdef inline u64 _cur(self): return self.cur
    cdef inline set_cur(self, u64 cur): self.cur = cur
    cdef inline void* _data(self): return self.data
    cdef inline u8 _level(self): return self.level
    cpdef UintSet init(self, u64 level):
        self.cur = 0
        cdef u64 count = (1 << level), deleted_size=(count>>3)+1 if count&7 else count>>3
        self.data = py_calloc(self._itemsize()*count)
        return self

cdef class U8BitSet(UintSet):
    cdef u64[4] data
    cdef readonly u64 cur

    cdef uintSetArgs * _arg(self):
        return &U8SET_ARGS
    cdef inline _get_arg_funcs(self, uintSetArgs** arg, uintSetFuncs** func):
        func[0] = &BitSetFuncs
        arg[0] = &U8SET_ARGS
    cdef inline u64 _itemsize(self): return self.itemsize
    cpdef UintBitSet set_itemsize(self, u8 itemsize):
        return self
    cdef u8 _level(self):
        return 1
    cdef inline u64 _cur(self): return self.cur
    cdef inline set_cur(self, u64 cur): self.cur = cur
    cdef inline void * _data(self): return self.data
    cdef inline u64 _nbytes(self):
        return 32# 2**(8*itemsize) /8
    cpdef UintSet init(self, u64 level):
        self.cur = 0
        self.data[0]=0; self.data[1]=0; self.data[2]=0; self.data[3]=0
        return self

cdef class UintBitSet(UintSet):
    cdef void* data
    cdef readonly u64 cur, itemsize
    cdef uintSetArgs * _arg(self):
        cdef u8 itemsize = self._itemsize()
        cdef uintSetArgs * arg = UINT_BIT_SET_ARGS+itemsize
        return arg
    cdef inline _get_arg_funcs(self, uintSetArgs** arg, uintSetFuncs** func):
        func[0] = get_funcs(self._itemsize(), self._level())
        arg[0] = self._arg()
    cdef inline u64 _itemsize(self): return self.itemsize
    cpdef UintBitSet set_itemsize(self, u8 itemsize):
        self.itemsize=itemsize
        return self
    cdef u8 _level(self):
        return (1<<self.itemsize)-8-log2(self.itemsize)
    cdef inline u64 _cur(self): return self.cur
    cdef inline set_cur(self, u64 cur): self.cur = cur
    cdef inline void* _data(self): return self.data
    cdef inline u64 _nbytes(self):
        (ONE<<(self.itemsize<<3))>>3 # 2**(8*itemsize) /8
    cpdef UintSet init(self, u64 level):
        self.cur = 0
        self.data = py_calloc(self._nbytes())
        return self

#--------------------------------------------------u16 array set------------------------------------------------
cdef class U16ArraySet(UintArraySet):
    cdef u64 _itemsize(self): return 16
cdef class U16HashSet(UintHashSet):
    cdef u64 _itemsize(self): return 16

cdef class U16ArraySet7(UintArraySet):
    cdef readonly u16[7] data
    cdef void* _data(self): return self.data

cdef class U16ArraySet15(UintArraySet):
    cdef readonly u16[15] data
    cdef void* _data(self): return self.data

cdef class U16ArraySet23(UintArraySet):
    cdef readonly u16[23] data
    cdef void* _data(self): return self.data

cdef class U16ArraySet31(UintArraySet):
    cdef readonly u16[31] data
    cdef void* _data(self): return self.data

cdef class U16ArraySet39(UintArraySet):
    cdef readonly u16[39] data
    cdef void* _data(self): return self.data

cdef tuple u16arraysets=(U16ArraySet7,U16ArraySet15,U16ArraySet23,U16ArraySet31,U16ArraySet39)
UINT_ARRAY_CLASSES[2]=u16arraysets

#--------------------------------------------------u32 array set------------------------------------------------
cdef class U32ArraySet(UintArraySet):
    cdef u64 _itemsize(self): return 32
cdef class U32HashSet(UintHashSet):
    cdef u64 _itemsize(self): return 32

cdef class U32ArraySet5(UintArraySet):
    cdef readonly u32[5] data
    cdef void* _data(self): return self.data

cdef class U32ArraySet13(UintArraySet):
    cdef readonly u32[13] data
    cdef void* _data(self): return self.data

cdef class U32ArraySet21(UintArraySet):
    cdef readonly u32[21] data
    cdef void* _data(self): return self.data

cdef class U32ArraySet29(UintArraySet):
    cdef readonly u32[29] data
    cdef void* _data(self): return self.data

cdef class U32ArraySet37(UintArraySet):
    cdef readonly u32[37] data
    cdef void* _data(self): return self.data

cdef tuple u32arraysets=(U32ArraySet5,U32ArraySet13,U32ArraySet21,U32ArraySet29,U32ArraySet37)
UINT_ARRAY_CLASSES[4]=u32arraysets

#--------------------------------------------------u24 array set------------------------------------------------
cdef class U24ArraySet(UintArraySet):
    cdef u64 _itemsize(self): return 24
cdef class U24HashSet(UintHashSet):
    cdef u64 _itemsize(self): return 24

cdef class U24ArraySet5(UintArraySet):
    cdef readonly u8[5] data
    cdef void* _data(self): return self.data

cdef class U24ArraySet13(UintArraySet):
    cdef readonly u8[13] data
    cdef void* _data(self): return self.data

cdef class U24ArraySet21(UintArraySet):
    cdef readonly u8[21] data
    cdef void* _data(self): return self.data

cdef class U24ArraySet29(UintArraySet):
    cdef readonly u8[29] data
    cdef void* _data(self): return self.data

cdef class U24ArraySet37(UintArraySet):
    cdef readonly u8[37] data
    cdef void* _data(self): return self.data

cdef tuple u24arraysets=(U24ArraySet5,U24ArraySet13,U24ArraySet21,U24ArraySet29,U24ArraySet37)
UINT_ARRAY_CLASSES[3]=u24arraysets

#--------------------------------------------------u40 array set------------------------------------------------
cdef class U40ArraySet(UintArraySet):
    cdef u64 _itemsize(self): return 40
cdef class U40HashSet(UintHashSet):
    cdef u64 _itemsize(self): return 40

cdef class U40ArraySet3(UintArraySet):
    cdef readonly u8[3] data
    cdef void* _data(self): return self.data

cdef class U40ArraySet11(UintArraySet):
    cdef readonly u8[11] data
    cdef void* _data(self): return self.data

cdef class U40ArraySet19(UintArraySet):
    cdef readonly u8[19] data
    cdef void* _data(self): return self.data

cdef class U40ArraySet27(UintArraySet):
    cdef readonly u8[27] data
    cdef void* _data(self): return self.data

cdef class U40ArraySet35(UintArraySet):
    cdef readonly u8[35] data
    cdef void* _data(self): return self.data

cdef tuple u40arraysets=(U40ArraySet3,U40ArraySet11,U40ArraySet19,U40ArraySet27,U40ArraySet35)
UINT_ARRAY_CLASSES[5]=u40arraysets

#--------------------------------------------------u48 array set------------------------------------------------
cdef class U48ArraySet(UintArraySet):
    cdef u64 _itemsize(self): return 48
cdef class U48HashSet(UintHashSet):
    cdef u64 _itemsize(self): return 48

cdef class U48ArraySet5(UintArraySet):
    cdef readonly u8[5] data
    cdef void* _data(self): return self.data

cdef class U48ArraySet13(UintArraySet):
    cdef readonly u8[13] data
    cdef void* _data(self): return self.data

cdef class U48ArraySet21(UintArraySet):
    cdef readonly u8[21] data
    cdef void* _data(self): return self.data

cdef class U48ArraySet29(UintArraySet):
    cdef readonly u8[29] data
    cdef void* _data(self): return self.data

cdef class U48ArraySet37(UintArraySet):
    cdef readonly u8[37] data
    cdef void* _data(self): return self.data

cdef tuple u48arraysets=(U48ArraySet5,U48ArraySet13,U48ArraySet21,U48ArraySet29,U48ArraySet37)
UINT_ARRAY_CLASSES[6]=u48arraysets

#--------------------------------------------------u64 array set------------------------------------------------
cdef class U64ArraySet(UintArraySet):
    cdef u64 _itemsize(self): return 64
cdef class U64HashSet(UintHashSet):
    cdef u64 _itemsize(self): return 64

cdef class U64ArraySet4(UintArraySet):
    cdef readonly u64[4] data
    cdef void* _data(self): return self.data

cdef class U64ArraySet12(UintArraySet):
    cdef readonly u64[12] data
    cdef void* _data(self): return self.data

cdef class U64ArraySet20(UintArraySet):
    cdef readonly u64[20] data
    cdef void* _data(self): return self.data

cdef class U64ArraySet28(UintArraySet):
    cdef readonly u64[28] data
    cdef void* _data(self): return self.data

cdef class U64ArraySet36(UintArraySet):
    cdef readonly u64[36] data
    cdef void* _data(self): return self.data

cdef tuple u64arraysets=(U64ArraySet4,U64ArraySet12,U64ArraySet20,U64ArraySet28,U64ArraySet36)
UINT_ARRAY_CLASSES[8]=u64arraysets
 

